package com.molichuxing.gateway.bff.user.services.impl;

import java.time.LocalDateTime;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONObject;
import com.moli.iov.util.Md5PwdEncoder;
import com.molichuxing.framework.contants.RedisKeyConst;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.CheckIdCardUtil;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.Md5Util;
import com.molichuxing.framework.utils.RandomCode;
import com.molichuxing.framework.utils.RedisUtil;
import com.molichuxing.framework.utils.ValidateUtil;
import com.molichuxing.gateway.bff.user.convertor.Convert;
import com.molichuxing.gateway.bff.user.entity.request.create.IdentityCardCreateVo;
import com.molichuxing.gateway.bff.user.entity.request.create.IdentityCardImgCreateVo;
import com.molichuxing.gateway.bff.user.entity.request.create.UserCreateVo;
import com.molichuxing.gateway.bff.user.entity.request.modify.AccountModifyVo;
import com.molichuxing.gateway.bff.user.entity.request.modify.UserModifyVo;
import com.molichuxing.gateway.bff.user.entity.response.AccountVo;
import com.molichuxing.gateway.bff.user.entity.response.UserLoginVo;
import com.molichuxing.gateway.bff.user.entity.response.UserVo;
import com.molichuxing.gateway.bff.user.services.TerminalUserBffService;
import com.molichuxing.gateway.property.UserPasswordTypeEnum;
import com.molichuxing.gateway.property.UserTypeEnum;
import com.molichuxing.gateway.utils.redis.TokenUtil;
import com.molichuxing.services.business.dto.request.create.EsignAccountBizCreateDto;
import com.molichuxing.services.business.dto.request.create.MobileCreateDto;
import com.molichuxing.services.business.dto.request.create.UserBizCreateDto;
import com.molichuxing.services.business.dto.request.modify.UserBizModifyDto;
import com.molichuxing.services.business.dto.response.StoreBaseBizDto;
import com.molichuxing.services.business.dto.response.UserBizDto;
import com.molichuxing.services.business.service.AccountBizService;
import com.molichuxing.services.business.service.EsignBizService;
import com.molichuxing.services.business.service.MobileBizService;
import com.molichuxing.services.business.service.SmsBizService;
import com.molichuxing.services.business.service.StoreBizService;
import com.molichuxing.services.business.service.UserBizService;
import com.molichuxing.services.infrastructure.dto.request.create.IdentityCardImgCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.PhoneRecognitionCreateDto;
import com.molichuxing.services.infrastructure.dto.response.RegionInfoDto;
import com.molichuxing.services.infrastructure.dto.response.UserDto;
import com.molichuxing.services.infrastructure.dto.response.response.AccountDto;
import com.molichuxing.services.infrastructure.service.CreditRecognitionService;
import com.molichuxing.services.infrastructure.service.IdentityCardImgService;
import com.molichuxing.services.infrastructure.service.PhoneRecognitionService;
import com.molichuxing.services.infrastructure.service.RegionService;
import com.molichuxing.services.infrastructure.service.UserService;
import com.molichuxing.services.property.SmsTemplateEnum;
import com.molichuxing.services.property.VerifyResultEnum;

@Service("terminalUserBffService")
public class TerminalUserBffServiceImpl implements TerminalUserBffService {
	
	private static final Logger logger = LoggerFactory.getLogger(TerminalUserBffServiceImpl.class);
	
	// 环境
	@Value("${profiles.active}")
	private String active;
	@Value("${verify.days}")
	private Integer verifyDays;
	@Value("${white.list.id.number}")
 	private String whiteListIdNumber;
    @Value("${auth.is.true}")
    private boolean authIsTrue;
    @Value("${auth.code}")
	private String authCode;
    @Value("${password.salt}")
    private String passwordSalt;
	
	private final static String IDNUMBER ="辽宁,吉林,黑龙江";
	
	private final static String IDNUMBERNOPASS ="台湾,香港,澳门,国外";
	
	private final static String USERNAME ="moli";	
	
	private final static String PHONE ="170,171,165";
	
	@Resource
	private RedisUtil redisUtil;
	@Resource
	private TokenUtil tokenUtil;
	@Resource
	private UserService userService;
	@Resource
	private UserBizService userBizService;
	@Resource
	private RegionService regionService;
	@Resource
	private PhoneRecognitionService phoneRecognitionService;
	@Resource
	private MobileBizService mobileBizService;
	@Resource
	private CreditRecognitionService creditRecognitionService;
	@Resource
	private StoreBizService storeBizService;
	@Resource
	private AccountBizService accountBizService;
	@Resource
	private SmsBizService smsBizService;
	@Resource
	private EsignBizService esignBizService;
	@Resource
	private IdentityCardImgService IdentityCardImgService;
	
	/**
	 * 大屏读取身份证接口
	 * @param createVo
	 * @return
	 */
	@Override
	public ResponseResult<UserLoginVo> createIdentityCard(IdentityCardCreateVo createVo) {
		validateParams(createVo);
		String idNumber= createVo.getIdNumber();
		//验证身份证
		validateIdNumber(idNumber);
		UserBizDto user = userBizService.getUser(idNumber);
		if(null == user) {
			return createUser(createVo);
		}
		return modifyUser(createVo,user);
	}
	
	/**
	 * 验证参数
	 * @param createVo
	 */
	private void validateParams(IdentityCardCreateVo createVo) {
		Assert.notNull(createVo,"参数不能为空");
		Assert.hasLength(createVo.getName(), "姓名不能为空");
		Assert.hasLength(createVo.getIdNumber(), "身份证号不能为空");
		Assert.hasLength(createVo.getAddress(), "地址不能为空");
	}
	
	/**
	 * 验证身份证
	 * @param idNumber
	 */
	private void validateIdNumber(String idNumber){
		String[] splitWhiteList = whiteListIdNumber.split(",");
		for (String whiteList : splitWhiteList) {
			if(whiteList.equals(idNumber)) {
				return ;
			}
		}
		
		if(!CheckIdCardUtil.validateCard(idNumber)) {
			throw new BizException(101,"抱歉，您未通过身份识别");
		}
		
		String province = CheckIdCardUtil.getProvinceByIdCard(idNumber);
		String[] idNumberNoPass = IDNUMBERNOPASS.split(",");
		for (String str : idNumberNoPass) {
			if(str.equals(province)) {
				throw new BizException(101,"抱歉，暂不受理港澳台同胞及外籍户籍人群");
			}
		}
		
		String[] splitNumber = IDNUMBER.split(",");
		for (String str : splitNumber) {
			if(str.equals(province)) {
				throw new BizException(101,"抱歉，您未通过身份识别");
			}
		}
	}
	
	/**
	 * 新用户
	 * @param createVo
	 * @return
	 */
	private ResponseResult<UserLoginVo> createUser(IdentityCardCreateVo createVo) {
		UserVo userVo = new UserVo();	
		userVo.setIdNumber(createVo.getIdNumber());
		userVo.setRealName(createVo.getName());
		userVo.setIdNumberAddress(createVo.getAddress());
		String terminalToken = tokenUtil.setTerminalUserToken(userVo);
		UserLoginVo userLoginVo = new UserLoginVo();
		userLoginVo.setUserVo(userVo);
		userLoginVo.setToken(terminalToken);
		userLoginVo.setIsNew(true);
        return new ResponseResult<UserLoginVo>().success(userLoginVo);
	}
	
	/**
	 * 老用户
	 * @param createVo
	 * @return
	 */
	private ResponseResult<UserLoginVo> modifyUser(IdentityCardCreateVo createVo,UserBizDto user) {
		UserVo userVo = new UserVo();	
        if(StringUtils.isNoneBlank(user.getRealName())) {
        	if(!createVo.getName().equals(user.getRealName())) {
        		return new ResponseResult<UserLoginVo>().error("用户姓名不正确");
        	}
        }
        userVo.setUserId(user.getId());
        userVo.setPhone(user.getPhone());
        userVo.setName(user.getName());
        userVo.setRealName(createVo.getName());
        userVo.setIdNumber(createVo.getIdNumber());
        userVo.setIdNumberAddress(createVo.getAddress());
		String terminalToken = tokenUtil.setTerminalUserToken(userVo);
		UserLoginVo userLoginVo = new UserLoginVo();
		userLoginVo.setUserVo(userVo);
		userLoginVo.setToken(terminalToken);
		userLoginVo.setIsNew(false);
        return new ResponseResult<UserLoginVo>().success(userLoginVo);
	}
	
	/**
	 * 大屏手机注册接口
	 * @param createVo
	 * @param terminalToken
	 * @return
	 */
	@Override
	public ResponseResult<String> createUser(UserCreateVo createVo,String terminalToken) {
		validateParams(createVo);
		
		//万能验证码
		if(!(authIsTrue && authCode.equals(createVo.getVerificationCode()))) {
			//短信验证码key
			String verificationCodeKey=RedisKeyConst.SMS_USER_CODE_LOGIN+Md5Util.md5Hex(active+UserTypeEnum.TERMINAL_USER.getValue())+"."+Md5Util.md5Hex(createVo.getPhone());
			String verificationCodeStr = redisUtil.get(verificationCodeKey);
			verificationCodeStr = verificationCodeStr==null ? "" : verificationCodeStr;
			if(!verificationCodeStr.equals(createVo.getVerificationCode())) {
	            return  new ResponseResult<String>(1,"验证码错误，请重新输入"); 
			}
		}
		UserVo userVo = tokenUtil.getUserVo(terminalToken);
		UserBizDto userDto = userBizService.getUserByPhone(createVo.getPhone());
		//验证用户信息
		validateUser(createVo, userVo, userDto);
		Integer userId = userVo.getUserId();
		if(null != userDto) {
			userId = userDto.getId();
		}
		
		Boolean flagPhone = phoneRecognitionService.getVerifyResult(userId, DateUtil.getNDays(-verifyDays));
		if(!flagPhone) {
			MobileCreateDto createDto = new MobileCreateDto();
			createDto.setIdNumber(userVo.getIdNumber());
			createDto.setRealName(userVo.getRealName());
			createDto.setPhone(createVo.getPhone());
			ResponseResult<String> respone = mobileBizService.getMoblie(createDto);
			if(!respone.getCode().equals(0)) {
	    		if(null != userId) {
	    			savePhoneRecognitionService(createVo.getPhone(),VerifyResultEnum.NO_PASS.getValue(),userId);
	    		}
	    		respone.setCode(453);
	    		respone.setMessage("手机号实名信息与身份证信息不一致");
	        	return respone;
	    	}
		}
		return createUser(createVo,userVo,userDto,terminalToken,flagPhone);
	}
	
	/**
	 * 验证登录参数
	 * @param createVo
	 */
	private void validateParams(UserCreateVo createVo){
		Assert.notNull(createVo,"参数不能为空");
		validatePhone(createVo.getPhone());
		Assert.notNull(createVo.getUserSource(),"数据来源不能为空");
		Assert.notNull(createVo.getVerificationCode(),"验证码不能为空");
	}
	
	/**
	 * 验证手机号
	 * @param phone
	 */
	private void validatePhone(String phone) {
		Assert.hasLength(phone, "参数不能为空");
		if(phone.length() != 11 || !phone.startsWith("1")) {
			throw new BizException(400,"手机号格式不正确");
		}
		String[] splitPhone = PHONE.split(",");
		for (String str : splitPhone) {
			if(phone.startsWith(str)) {
				throw new BizException(1,"暂不支持170、171、165号段的手机号");
			}
		}
	}
    
	/**
	 * 用户注册登录（大屏）
	 * @param createVo
	 * @param userVo
	 * @param userDto
	 * @param terminalToken
	 * @param flagPhone
	 * @return
	 */
	private ResponseResult<String> createUser(UserCreateVo createVo,UserVo userVo,UserBizDto userDto,
			String terminalToken,Boolean flagPhone){
			
		//注册
		if(null == userDto) {
			UserBizCreateDto userBizCreateDto = new UserBizCreateDto();
			String name = getName();
			userBizCreateDto.setName(name);
			userBizCreateDto.setPhone(createVo.getPhone());
			userBizCreateDto.setSource(createVo.getUserSource());
			userBizCreateDto.setRealName(userVo.getRealName());
			userBizCreateDto.setIdNumber(userVo.getIdNumber());
			userBizCreateDto.setAddress(userVo.getIdNumberAddress());
			userBizService.createUser(userBizCreateDto);
			//重新设置用户信息
			setTerminalUserToken(createVo.getPhone(),terminalToken);
			//生成用户印章信息
			createEsignAccount(userVo.getIdNumber(),userVo.getRealName(),createVo.getPhone());
			return new ResponseResult<String>().success("注册成功");
		}
		
		if(!flagPhone) {
			savePhoneRecognitionService(createVo.getPhone(),VerifyResultEnum.PASS.getValue(),userDto.getId());
		}
		//登录
		UserBizModifyDto userBizModifyDto =new UserBizModifyDto();
		userBizModifyDto.setId(userDto.getId());
		userBizModifyDto.setRealName(userVo.getRealName());
		userBizModifyDto.setIdNumber(userVo.getIdNumber());
		userBizModifyDto.setIdNumberAddress(userVo.getIdNumberAddress());
		userBizService.modifyUserTerminal(userBizModifyDto);
		//重新设置用户信息
		getUserByUserId(userDto.getId(),terminalToken);
		//生成用户印章信息
		createEsignAccount(userVo.getIdNumber(),userVo.getRealName(),createVo.getPhone());
		return new ResponseResult<String>().success("登录成功");
	}
	
	/**
	 * 注册成功发送短信
	 * @param userVo
	 */
	private void sendNote(UserVo userVo) {
		JSONObject json=new JSONObject();
	    json.put("name", userVo.getName());
	    try {
	    	smsBizService.sendMessage(userVo.getPhone(), SmsTemplateEnum.NEW_USER_REGISTER.getValue(), json.toJSONString(), null);
		} catch (Exception e) {
			logger.error("新用户注册发送短信失败",e);
		}
	}
	
	/**
	 * 重新设置用户信息
	 * @param phone
	 * @param terminalToken
	 */
	private void setTerminalUserToken(String phone,String terminalToken) {
		UserBizDto userBizDto = userBizService.getUserByPhone(phone);
		UserVo userVo = Convert.toUserVo(userBizDto);
		if(null == userVo) {
			throw new BizException(101,"不存在该用户信息");
		}
		//获取省市区信息
		getCity(userBizDto,userVo);
		tokenUtil.setTerminalUser(terminalToken,userVo);
		//注册成功发送短信
		sendNote(userVo);
		savePhoneRecognitionService(phone,VerifyResultEnum.PASS.getValue(),userBizDto.getId());
	}
	
	 /**
     * 重新设置用户信息
     * @param userId
     * @param terminalToken
     */
    private void getUserByUserId(Integer userId,String terminalToken) {
    	UserBizDto userBizDto = userBizService.getUser(userId);
		UserVo userVo = Convert.toUserVo(userBizDto);
		if(null == userVo) {
			throw new BizException(101,"不存在该用户信息");
		}
		//获取省市区信息
		getCity(userBizDto,userVo);
		tokenUtil.setTerminalUser(terminalToken,userVo);
		tokenUtil.modifyUserToken(userVo);
		tokenUtil.modifyWechatUserToken(userVo);
    }
    
    /**
     * 
     * @param userBizDto
     * @param userVo
     */
    private void getCity(UserBizDto userBizDto,UserVo userVo) {
    	if(null == userBizDto) {
    		return;
    	}
    	if(null == userBizDto.getRegionId()) {
    		return;
    	}
    	RegionInfoDto city= regionService.getCityNameByAreaId(userVo.getRegionId());
		if(null != city) {
			userVo.setProvinceId(city.getProvinceId());
			userVo.setCityId(city.getCityId());
			userVo.setRegionName(city.getProvinceFullName()+city.getCityFullName()+city.getAreaFullName());
		}
    }
    
	/**
	 * 获取默认生成的用户名
	 * @return
	 */
	private String getName() {
		String name = RandomCode.randomString(4);
		name=USERNAME+name;
		UserDto user = userService.getUserByName(name);
		if(null == user) {
			return name;
		}
		getName();
		return name;
	}
	
	/**
	 * 保存三要素验证结果
	 * @param phone
	 * @param verifyResult
	 * @param userId
	 */
	private void savePhoneRecognitionService(String phone,Integer verifyResult,Integer userId) {
		PhoneRecognitionCreateDto createDto =new PhoneRecognitionCreateDto();
		createDto.setUserId(userId);
		createDto.setPhone(phone);
		createDto.setVerifyResult(verifyResult);
		createDto.setVerifyTime(LocalDateTime.now());
		phoneRecognitionService.create(createDto);
	}
	
	/**
	 * 验证用户信息
	 * @param createVo
	 * @param userVo
	 * @param userDto
	 */
	private void validateUser(UserCreateVo createVo, UserVo userVo, UserBizDto userDto) {
		if(StringUtils.isNoneBlank(userVo.getPhone())) {
			if(!userVo.getPhone().equals(createVo.getPhone())) {
				throw new BizException(453,"手机号实名信息与身份证信息不一致");
			}
		}
		if(null != userDto) {
		  if(StringUtils.isNoneBlank(userDto.getRealName())) {{
				if(!userVo.getRealName().equals(userDto.getRealName())) {
					throw new BizException(453,"手机号实名信息与身份证信息不一致");
				}
		    }
		  }
		  if(StringUtils.isNoneBlank(userDto.getIdNumber())) {{
				if(!userVo.getIdNumber().equals(userDto.getIdNumber())) {
					throw new BizException(453,"手机号实名信息与身份证信息不一致");
				}
		    }
		  }
		  if(null != userVo.getUserId()) {{
				if(!userVo.getUserId().equals(userDto.getId())) {
					throw new BizException(453,"手机号实名信息与身份证信息不一致");
				}
		    }
		  }
	   }  
	}
	
	/**
	 * 大屏修改用户信息
	 * @param modifyVo
	 * @param terminalToken
	 * @return
	 */
	@Override
	public Boolean modifyUser(UserModifyVo modifyVo, String terminalToken) {
		
		validateParams(modifyVo);
		UserVo userVo = tokenUtil.getUserVo(terminalToken);
		UserBizModifyDto modifyDto = new UserBizModifyDto();
		modifyDto.setId(userVo.getUserId());
		modifyDto.setAddress(modifyVo.getAddress());
		modifyDto.setEmail(modifyVo.getEmail());
		modifyDto.setRegionId(modifyVo.getRegionId());
		Boolean flag = userBizService.modifyUserEmail(modifyDto);
		//重新设置用户信息
		getUserByUserId(userVo.getUserId(),terminalToken);
		return flag;
	}
	
	/**
	 * 验证大屏修改用户信息参数
	 * @param modifyVo
	 */
	private void validateParams(UserModifyVo modifyVo){
		Assert.notNull(modifyVo,"参数不能为空");
		Assert.notNull(modifyVo.getRegionId(),"地址不能为空");
		Assert.hasLength(modifyVo.getAddress(), "地址不能为空");
		String email = modifyVo.getEmail();
		Assert.hasLength(email, "地址不能为空");
		if(!ValidateUtil.isValidEmail(email)) {
			throw new BizException(101,"邮箱格式不正确");
		}
	}
	
	/**
	 * 跟cpu号查询销售顾问账号
	 * @param deviceNum cpu号
	 * @return
	 */
	@Override
	public List<AccountVo> getStroeAccount(String deviceNum) throws Exception{
		Assert.hasLength(deviceNum,"cpu不能为空");
		StoreBaseBizDto store= storeBizService.getStoreBaseByCpu(deviceNum);
		if(null == store) {
			throw new BizException(101,"该门店信息不存在");
		}
		List<AccountDto> list = accountBizService.getSmartTerminalAccountByDealer(store.getDealerId());
		List<AccountVo> voList = Convert.toAccountVo(list);
		return voList;
	}
	
	/**
	 * 大屏销售顾问登录接口
	 * @param modifyVo
	 * @return
	 */
	@Override
	public ResponseResult<String> counselorLogin(AccountModifyVo modifyVo) {
		
		AccountDto account = accountBizService.getSmartTerminalAccount(modifyVo.getId(), modifyVo.getPhone());
		String password = modifyVo.getPassword();
		if(null == account || null == account.getId()) {
			 return  new ResponseResult<String>(1,"密码或账号错误"); 
		}
		if(UserPasswordTypeEnum.VERIFICATION_CODE.getValue() == modifyVo.getPasswordType()) {
			if(!(authIsTrue && authCode.equals(password))) {	
				//短信验证码key
				String verificationCodeKey=RedisKeyConst.SMS_USER_CODE_LOGIN+Md5Util.md5Hex(active+UserTypeEnum.COUNSELOR_USER.getValue())+"."+Md5Util.md5Hex(modifyVo.getPhone());
				String verificationCodeStr = redisUtil.get(verificationCodeKey);
				verificationCodeStr = verificationCodeStr==null ? "" : verificationCodeStr;
				if(!verificationCodeStr.equals(password)) {
		            return  new ResponseResult<String>(1,"验证码错误，请重新输入"); 
				}
			}
		}else {
			String encodePassword = Md5PwdEncoder.encodePassword(password, passwordSalt);
			if(!encodePassword.equals(account.getPassword())) {
				return  new ResponseResult<String>(1,"密码错误，请重新输入"); 
			}
		}
		
		AccountVo accountVo = Convert.toAccountVo(account);
		String counselorUserToken = tokenUtil.setCounselorUserToken(accountVo);
		return new ResponseResult<String>().success(counselorUserToken);
	}
	
	/**
	 * 生成用户印章信息
	 * @param idNumber
	 * @param realName
	 * @param phone
	 */
	private void createEsignAccount(String idNumber,String realName,String phone) {
		EsignAccountBizCreateDto dto = new EsignAccountBizCreateDto();
		dto.setIdNo(idNumber);
		dto.setMobile(phone);
		dto.setName(realName);
		try {
			esignBizService.createEsignAccount(dto);
		} catch (Exception e) {
			logger.error("用生成印章信息失败",e);
		}
	}
	
	/**
	 * 保存身份证图片信息
	 * @param createVo
	 * @return
	 */
	@Override
	public Boolean createCardImg(IdentityCardImgCreateVo createVo) {
		IdentityCardImgCreateDto createDto = new IdentityCardImgCreateDto();
		BeanUtils.copyProperties(createVo, createDto);
		return IdentityCardImgService.create(createDto);
	}
}
